
#pragma once

#include "zdbmain.h"
#include "zdbents.h"
#include "zAcString.h"
#include "zadscodes.h"
#include "zadsdef.h"

#pragma pack(push, 8)
class  UcDbEvalGraph;
class  UcDbEvalEdgeInfo;
class  UcDbEvalExpr;
class  UcDbEvalCoectable;
class  UcDbEvalContext;
class  UcDbEvalContextPair;
class  UcDbEvalContextIterator;
class  UcDbEvalVariant;
class  UcDbImpEvalContext;
class  UcDbImpEvalContextIterator;

typedef ZSoft::UInt32 UcDbEvalNodeId;
typedef UcArray<UcDbEvalNodeId>             UcDbEvalNodeIdArray;
typedef UcArray<UcDbEvalEdgeInfo*>          UcDbEvalEdgeInfoArray;
typedef UcArray<UcDbEvalExpr*>              UcDbEvalExprPtrArray;
typedef UcArray<UcDbEvalVariant,
        UcArrayObjectCopyReallocator<UcDbEvalVariant> >   UcDbEvalVariantArray;

class UcDbEvalVariant : public resbuf, public UcRxObject
{
public:

    UCRX_DECLARE_MEMBERS(UcDbEvalVariant);
    UcDbEvalVariant ();
    UcDbEvalVariant(const UcDbEvalVariant& other);
    UcDbEvalVariant (const UcDbEvalVariant* pOther);
    ~UcDbEvalVariant();
    UcDbEvalVariant (double       dVal);
    UcDbEvalVariant (short        iVal);
    UcDbEvalVariant (const ZTCHAR*  szVal);
    UcDbEvalVariant (ZSoft::Int32       lVal);
    UcDbEvalVariant (const UcDbObjectId& id);
    UcDbEvalVariant (const UcGePoint2d&  pt);
    UcDbEvalVariant (const UcGePoint3d&  pt);
    UcDbEvalVariant& operator=(double      dVal);
    UcDbEvalVariant& operator=(short       iVal);
    UcDbEvalVariant& operator=(ZSoft::Int32 lVal);
    UcDbEvalVariant& operator=(const ZTCHAR* szVal);
    UcDbEvalVariant& operator=(const UcDbEvalVariant& other);
    UcDbEvalVariant& operator=(const UcDbObjectId& id);
    UcDbEvalVariant& operator=(const UcGePoint2d&  pt);
    UcDbEvalVariant& operator=(const UcGePoint3d&  pt);
	
    void clear();
    virtual Ucad::ErrorStatus copyFrom(const UcRxObject* pOther);

protected:
    void init();

};

class UcDbEvalEdgeInfo;

class UcDbEvalIdMap
{
public:
    virtual UcDbEvalNodeId find(const UcDbEvalNodeId& key) = 0;
    virtual void kill() = 0;
};

class UcDbEvalGraph : public UcDbObject
{
public:
    enum NodeId {
        kNullNodeId = 0
    };

    UCDB_DECLARE_MEMBERS(UcDbEvalGraph);
    UcDbEvalGraph();
    virtual ~UcDbEvalGraph();
    static bool hasGraph(const UcDbObject*    pObj,
                         const ZTCHAR*          pKey);
    static Ucad::ErrorStatus getGraph(const UcDbObject*    pObj,
                                      const ZTCHAR*          pKey,
                                      UcDbEvalGraph**      pGraph,
                                      const UcDb::OpenMode mode);
    static Ucad::ErrorStatus createGraph(UcDbObject* pObj,
                                         const ZTCHAR* pKey);
    static Ucad::ErrorStatus removeGraph(UcDbObject* pObj,
                                         const ZTCHAR* pKey);
    static bool hasGraph(UcDbDatabase*        pDb,
                         const ZTCHAR*          pKey);
    static Ucad::ErrorStatus getGraph(UcDbDatabase*        pDb,
                                      const ZTCHAR*          pKey,
                                      UcDbEvalGraph**      pGraph,
                                      const UcDb::OpenMode mode);
    static Ucad::ErrorStatus createGraph(UcDbDatabase* pDb,
                                         const ZTCHAR*   pKey);
    static Ucad::ErrorStatus removeGraph(UcDbDatabase* pDb,
                                         const ZTCHAR*   pKey);
    static Ucad::ErrorStatus replaceGraph(UcDbObject* pObj,
                                         const ZTCHAR* pKey,
                                         UcDbObjectId grphId);
    virtual Ucad::ErrorStatus addNode     (UcDbEvalExpr*   pNode,
                                           UcDbEvalNodeId& id);
    virtual Ucad::ErrorStatus removeNode  (const UcDbEvalNodeId& id);
    virtual Ucad::ErrorStatus removeNode  (UcDbEvalExpr* pNode);
    virtual Ucad::ErrorStatus getAllNodes (UcDbEvalNodeIdArray& nodes) const;
    virtual Ucad::ErrorStatus getNode     (const UcDbEvalNodeId& nodeId,
                                           UcDb::OpenMode        mode,
                                           UcDbObject**        ppNode) const;
    virtual Ucad::ErrorStatus addEdge(const UcDbEvalNodeId& idFrom,
                                      const UcDbEvalNodeId& idTo);
    virtual Ucad::ErrorStatus addEdge(const UcDbEvalNodeId& idFrom,
                                      const UcDbEvalNodeId& idTo,
                                      bool  bInvertible);
    virtual Ucad::ErrorStatus removeEdge(const UcDbEvalNodeId& idFrom,
                                         const UcDbEvalNodeId& idTo);
    virtual Ucad::ErrorStatus getIncomingEdges(const UcDbEvalNodeId& nodeId,
                                      UcDbEvalEdgeInfoArray& edges) const;
    virtual Ucad::ErrorStatus getOutgoingEdges(const UcDbEvalNodeId& nodeId,
                                      UcDbEvalEdgeInfoArray& edges) const;
    virtual Ucad::ErrorStatus getEdgeInfo(const UcDbEvalNodeId& nodeFrom,
            const UcDbEvalNodeId& nodeTo, UcDbEvalEdgeInfo& einfo) const;
    virtual Ucad::ErrorStatus addGraph(UcDbEvalGraph* pGraphToAdd,
                UcDbEvalIdMap*& idMap);
    virtual Ucad::ErrorStatus evaluate() const;
    virtual Ucad::ErrorStatus evaluate(
            const UcDbEvalContext*     pContext) const;
    virtual Ucad::ErrorStatus evaluate(
            const UcDbEvalContext*     pContext,
            const UcDbEvalNodeIdArray* activatedNodes) const;
    virtual Ucad::ErrorStatus activate(
            const UcDbEvalNodeIdArray& activatedNodes) const;
    virtual Ucad::ErrorStatus activate(
            const UcDbEvalNodeIdArray& activatedNodes,
            UcDbEvalNodeIdArray*       pActiveSubgraph) const;
    virtual Ucad::ErrorStatus activate(
            const UcDbEvalNodeIdArray& activatedNodes,
            UcDbEvalNodeIdArray*       pActiveSubgraph,
            UcDbEvalNodeIdArray*       pCycleNodes) const;
    virtual Ucad::ErrorStatus getIsActive(const UcDbEvalNodeId& id,
            bool& bIsActive) const;
    virtual bool equals(const UcDbEvalGraph* pOther) const;
    virtual bool isSubgraphOf(const UcDbEvalGraph* pOther) const;
    virtual Ucad::ErrorStatus postInDatabase(UcDbObjectId& objId, UcDbDatabase* pDb);

};

class UcDbEvalEdgeInfo
{
public:
    UcDbEvalEdgeInfo()
        : mFlags(0), mRefCount(0)
    {
        mIdFrom = UcDbEvalGraph::kNullNodeId;
        mIdTo = UcDbEvalGraph::kNullNodeId;
    }
    UcDbEvalEdgeInfo(UcDbEvalNodeId from,
                     UcDbEvalNodeId to,
                     ZSoft::Int32   flags,
                     ZSoft::UInt32  count)
        : mIdFrom(from), mIdTo(to), mFlags(flags), mRefCount(count)
        {}
    UcDbEvalNodeId from () const;
    UcDbEvalNodeId to   () const;
    ZSoft::UInt32 refCount() const;
    bool isInvertible () const;
    bool isSuppressed  () const;
    bool operator == (const UcDbEvalEdgeInfo& other) const;

private:
    UcDbEvalNodeId mIdFrom;
    UcDbEvalNodeId mIdTo;
    ZSoft::Int32  mFlags;
    ZSoft::UInt32 mRefCount;
};

class UcDbEvalExpr : public UcDbObject
{

public:
    UCDB_DECLARE_MEMBERS(UcDbEvalExpr);
    UcDbEvalExpr();
    virtual ~UcDbEvalExpr();
    Ucad::ErrorStatus getGraph(UcDbEvalGraph** pGraph,
                               UcDb::OpenMode  mode) const;
    UcDbEvalNodeId    nodeId() const;
    virtual void addedToGraph       (UcDbEvalGraph*  pGraph);
    virtual void removedFromGraph   (UcDbEvalGraph*  pGraph);
    virtual void adjacentNodeRemoved (const UcDbEvalNodeId& adjNodeId);
    virtual void adjacentEdgeRemoved (const UcDbEvalNodeId& adjEdgeNodeId);
    virtual void adjacentEdgeAdded (const UcDbEvalNodeId& fromId,
            const UcDbEvalNodeId& toId,
            bool bIsInvertible);
    virtual void movedFromGraph (UcDbEvalGraph* pFromGraph);
    virtual void movedIntoGraph (UcDbEvalGraph* pIntoGraph);
    virtual void remappedNodeIds (UcDbEvalIdMap& idMap);
    virtual void copiedIntoGraph(UcDbEvalGraph* pIntoGraph);
    virtual bool isActivatable  ();
    virtual void activated           (UcDbEvalNodeIdArray& argumentActiveList);
    virtual void graphEvalStart      (bool bNodeIsActive);
    virtual void graphEvalEnd        (bool bNodeIsActive);
    virtual void graphEvalAbort      (bool bNodeIsActive);
    virtual Ucad::ErrorStatus evaluate(const UcDbEvalContext* ctxt);
    virtual bool equals(const UcDbEvalExpr* pOther) const;
    UcDbEvalVariant value() const;
    virtual Ucad::ErrorStatus postInDatabase(UcDbObjectId& objId, UcDbDatabase* pDb);

protected:
    UcDbEvalVariant m_lastValue;
    friend class UcDbImpEvalExpr;
};

class UcDbEvalConnectable : public UcDbEvalExpr
{
public:
    UCDB_DECLARE_MEMBERS(UcDbEvalConnectable);
    virtual ~UcDbEvalConnectable();
    virtual Ucad::ErrorStatus getConnectionNames (UcStringArray& names) const;
    virtual bool              hasConnectionNamed (const UcString& name) const;
    virtual Ucad::ErrorStatus getConnectionType  (
                                    const UcString&        name,
                                    UcDb::DwgDataType& type) const;
    virtual Ucad::ErrorStatus getConnectionValue (
                                    const UcString&    name,
                                    UcDbEvalVariant&    value) const;
    virtual Ucad::ErrorStatus setConnectionValue (
                                    const UcString&       name,
                                    const UcDbEvalVariant& value);
    virtual Ucad::ErrorStatus connectTo (
                                const UcString&      thisConnection,
                                const UcDbEvalNodeId sourceConnectableId,
                                const UcString&      sourceConnectionName);
    virtual Ucad::ErrorStatus disconnectFrom (
                                const UcString&      thisConnection,
                                const UcDbEvalNodeId sourceConnectableId,
                                const UcString&      sourceConnectionName);
    virtual bool connectionAllowed ( 
                            const UcString&      thisConnection,
                            const UcDbEvalNodeId sourceConnectableId,
                            const UcString&      sourceConnectionName) const;
    virtual Ucad::ErrorStatus getConnectedObjects (
                                const UcString&      thisConnection,
                                UcDbEvalNodeIdArray& connectedObjects) const;
    virtual Ucad::ErrorStatus getConnectedNames (
                                const UcString&      thisConnection,
                                const UcDbEvalNodeId sourceConnectableId,
                                UcStringArray&       sourceConnectionNames) const;
protected:
    UcDbEvalConnectable();
};

class UcDbEvalContext : public UcRxObject, public UcHeapOperators
{
public:
    UcDbEvalContext();
    virtual ~UcDbEvalContext();

    UCRX_DECLARE_MEMBERS(UcDbEvalContext);
    virtual void        insertAt (const UcDbEvalContextPair& pair);
    virtual void        removeAt (const ZTCHAR*                szKey);
    virtual Ucad::ErrorStatus getAt (UcDbEvalContextPair& pair) const;
    virtual UcDbEvalContextIterator* newIterator() const;

private:
    UcDbImpEvalContext* mpImp;
    friend class UcDbImpEvalContextIterator;
};

class UcDbEvalContextPair : public UcHeapOperators
{
public:
    UcDbEvalContextPair();
    UcDbEvalContextPair(const ZTCHAR* szKey, void *pValue);
    virtual ~UcDbEvalContextPair();
    void        setKey   (const ZTCHAR* szKey);
    const ZTCHAR* key      () const;
    void        setValue (void* pValue);
    void*       value    () const;

private:
    ZTCHAR* mKey;
    void* mValue;
};

class UcDbEvalContextIterator : public UcRxObject, public UcHeapOperators
{
public:
    UcDbEvalContextIterator();
    virtual ~UcDbEvalContextIterator();

    UCRX_DECLARE_MEMBERS(UcDbEvalContextIterator);
    virtual void   start();
    virtual bool   next();
    virtual bool   done() const;
    virtual UcDbEvalContextPair contextPair() const;

private:
    UcDbEvalContextIterator(UcDbEvalContext* pContext);
    UcDbImpEvalContextIterator* mpImp;
    friend class UcDbImpEvalContext;
};

#pragma pack(pop)
